﻿using Kugar.Core.ExtMethod;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using Newtonsoft.Json.Linq;
using Senparc.Weixin.MP;
using Senparc.Weixin.MP.AdvancedAPIs;
using Senparc.Weixin.MP.Entities.Request;

namespace Kugar.Web.WechatMPOAuth
{
    /// <summary>
    /// 公众号回调的Controller
    /// </summary>
    
    public class MPCallbackController : Controller
    {
        internal static ConcurrentDictionary<string, IMPOAuthHandler> _cacheHanders = new ConcurrentDictionary<string, IMPOAuthHandler>();


        [Route("Core/MPCallback/Callback")]
        public async Task<ActionResult> Callback(string code, string state)
        {
            if (code == "" || state == "")
            {
                return new HttpUnauthorizedResult("已取消授权登陆");
            }

            var stateData = Session[state].ToStringEx();

            if (string.IsNullOrWhiteSpace(stateData))
            {
                return new HttpUnauthorizedResult("无效的回调");
            }

            //Session.Remove("WechatMPUser");

            var handlerTypeName=Session[$"{state}_handler"].ToStringEx();
            
            var handler = getMPHandler(handlerTypeName);

            //Session.Remove($"{state}_handler");
            
            var json = JObject.Parse(stateData);

            var scope = (OAuthScope) (int) json["Scope"];
            var backUrl = json.GetString("BackUrl");
            var appID = json.GetString("AppID");
            var appserect = json.GetString("AppSerect");

            var oauthUser =await OAuthApi.GetAccessTokenAsync(appID, appserect, code);

            var user = new WechatUserOAuth
                       {
                           OpenID = oauthUser.openid,
                           UnionID = oauthUser.unionid,
                           Scope = scope,
                           AccessToken = oauthUser.access_token
                       };


            if (scope == OAuthScope.snsapi_userinfo)
            {
                var wxUser =await OAuthApi.GetUserInfoAsync(oauthUser.access_token, oauthUser.openid);

                user.NickName = wxUser.nickname;
                user.HeaderPortraitUrl = wxUser.headimgurl;
            }

            Session["WechatMPUser"] = user;

            await handler.OnUserAuthorityAsync(appID,user,this);
            
            return Redirect(backUrl);
        }

        [Route("Core/MPCallback/service")]
        [HttpGet]
        public ActionResult Service(PostModel post)
        {
            return null;
        }

        [Route("Core/MPCallback/service")]
        [ActionName("Service")]
        [HttpPost]
        public ActionResult ServicePost(PostModel post)
        {
            return null;
        }

        internal static IMPOAuthHandler getMPHandler(string typeName)
        {
            return _cacheHanders.GetOrAdd(typeName, x =>
            {
                var type = AppDomain.CurrentDomain.GetAssemblies().SelectMany(y => y.GetTypes())
                    .Where(y => (y.Namespace + "." + y.Name) == typeName)
                    .FirstOrDefault();

                if (type==null)
                {
                    return null;
                }

                return (IMPOAuthHandler) Activator.CreateInstance(type);
            });
        }
    }


}
